package com.zte.claa.inficombo.csa.app.service.sapi.ffhost.mina;

import java.util.concurrent.atomic.AtomicInteger;

import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zte.claa.inficombo.csa.app.config.FFTransDevConnProps;

/**
 * @author 0283000115
 *
 * 一个sever对应一个消防用户信息传输装置的连接.
 * 初次创建后，应立即发送一个状态查询指令，以探测传输装置的编号，通知上层建立和相应设施的关联关系。
 */
public class FFTransDevConnServer {	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	// 和用户信息传输装置的会话.
	private IoSession session = null;
	// 连接参数.
	private FFTransDevConnProps connProps;
	// 下行命令流水号.
	private AtomicInteger SNO = null;
	// 用户信息传输装置地址（根据上报的地址更新）
	private byte[] transDevAddr = null;
	
	// 构建器.
	public FFTransDevConnServer(IoSession connSession, FFTransDevConnProps connProps){
		this.session = connSession;
		this.connProps = connProps;
		this.SNO = new AtomicInteger(0);
		// 立即启动一个线程查询用户信息传输装置的状态，主要是获取传输装置的编号，建立和装置对应资源实例的绑定关系.
		Thread t = new Thread(new Runnable(){
			@Override
			public void run() {
				try {
					sendTimeQueryCmd();
				} catch (Exception e) {
					logger.error("sendStateQueryCmd failed: "+e.getMessage(), e);
				}
			}
		});
		t.setName("FFTransDevConnServer temp thread");
		t.start();
	}
	
	// 下发传输装置时间查询命令.
	public void sendTimeQueryCmd() throws Exception {
		FFTransDevMessage msg = new FFTransDevMessage();
		msg.setCmd((byte)FFTransDevMessage.CMD_REQUEST);
		msg.setMsgTime(System.currentTimeMillis());
		msg.setSno(this.getMessageSno());
		msg.setSrcAddr(this.connProps.getLocaladdr().trim());
		if(transDevAddr == null){
			msg.setDstAdrr("0");
		} else {
			msg.setDstAddrBytes(transDevAddr);
		}
		// 查询传输装置的系统状态.
		msg.setData(new byte[]{88, 1, 0});
		// msg.setCheckSum(msg.calculateSumCheck());
		this.sendCommand(msg);
		logger.info("sendTimeQueryCmd ok: "+msg);
	}
	
	/**
	 * 释放session和connector.
	 */
	public void stopSvr() {
		if(this.session != null && !this.session.isClosing()){
			try{
				this.session.closeNow();
				this.session = null;
				logger.info("session close ok!");
			}catch(Exception ex){
				logger.error("Session close failed!", ex);
			}		
		}	
	}
	
	// 获取 SNO.
	public int getMessageSno(){
		int ret = this.SNO.incrementAndGet();
		if(ret > 65535){
			this.SNO = new AtomicInteger(0);
			ret = this.SNO.incrementAndGet();
		}
		return ret;
	}
	
	/**
	 * 下发命令。
	 * 
	 * @param cmd
	 * @throws Exception
	 */
	public WriteFuture sendCommand(FFTransDevMessage msg) throws Exception {
		if(session == null){
			throw new Exception("通信链路会话为空，网络不可达！");
		}
		if(msg.getSno() < 0){
			msg.setSno(this.getMessageSno());
		}
		msg.setCheckSum(msg.calculateSumCheck());
		return this.session.write(msg);  
	}

	public void setTransDevAddr(byte[] transDevAddr) {
		this.transDevAddr = transDevAddr;
	}

	public byte[] getTransDevAddr() {
		return transDevAddr;
	}
	
}
